home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / gs262 / gsimage1.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  15.7 KB  |  552 lines

  1. /* Copyright (C) 1989, 1992 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* gsimage1.c */
  20. /* Image procedures for Ghostscript library */
  21. /* This file is logically part of gsimage.c; we have split it out */
  22. /* to reduce the code working set. */
  23. #include "gx.h"
  24. #include "memory_.h"
  25. #include "gpcheck.h"
  26. #include "gserrors.h"
  27. #include "gxfixed.h"
  28. #include "gxarith.h"
  29. #include "gxmatrix.h"
  30. #include "gscspace.h"
  31. #include "gspaint.h"
  32. #include "gzstate.h"
  33. #include "gzdevice.h"            /* requires gsstate.h */
  34. #include "gzcolor.h"            /* requires gxdevice.h */
  35. #include "gzpath.h"
  36. #include "gxcolor.h"
  37. #include "gxcpath.h"
  38. #include "gxdevmem.h"
  39. #include "gximage.h"
  40.  
  41. #ifdef AMIGA
  42. extern void gx_set_device_only(gs_state *, gx_device *);
  43. extern int gx_check_tile_cache(gs_state *);
  44. extern int gx_color_load(gx_device_color *, const gs_state *);
  45. extern int gz_fill_pgram_fixed(fixed, fixed, fixed, fixed, fixed, fixed,
  46.                 const gx_device_color *, gs_state *);
  47. extern int gx_check_tile_size(gs_state *, int, int, int);
  48. #endif
  49.  
  50. /* Process the next piece of an image */
  51. int
  52. gs_image_next(register gs_image_enum *penum, byte *dbytes, uint dsize)
  53. {    uint rsize = penum->bytes_per_row;
  54.     uint pos = penum->byte_in_row;
  55.     int width = penum->width;
  56.     uint dleft = dsize;
  57.     uint dpos = 0;
  58.     gs_state *pgs = penum->pgs;
  59.     gx_device *save_dev = 0;
  60.     fixed xcur_save, ycur_save;
  61.     int y_save;
  62.     int code;
  63.     /* Accumulate separated colors, if needed */
  64.     if ( penum->plane_index == 0 )
  65.         penum->plane_size = dsize;
  66.     else if ( dsize != penum->plane_size )
  67.         return_error(gs_error_undefinedresult);
  68.     penum->planes[penum->plane_index] = dbytes;
  69.     if ( ++(penum->plane_index) != penum->spread )
  70.         return 0;
  71.     penum->plane_index = 0;
  72.     /* Save the dynamic state components in case of an error. */
  73.     xcur_save = penum->xcur;
  74.     ycur_save = penum->ycur;
  75.     y_save = penum->y;
  76.     /* We've accumulated an entire set of planes. */
  77.     if ( !penum->never_clip )
  78.        {    /* Install the clipping device if needed. */
  79.         gx_device *dev = (gx_device *)&penum->clip_dev;
  80.         save_dev = gs_currentdevice(pgs);
  81.         penum->clip_dev.target = save_dev;
  82.         gx_set_device_only(pgs, dev);
  83.        }
  84.     while ( dleft )
  85.        {    /* Fill up a row, then display it. */
  86.         uint bcount = min(dleft, rsize - pos);
  87.         byte *bptr =
  88.           penum->buffer + (pos << 3) / penum->bps * penum->spread;
  89.         int px;
  90.         for ( px = 0; px < penum->spread; px++ )
  91.           (*penum->unpack)(penum, &penum->map[px], bptr + px, penum->planes[px] + dpos, bcount, pos);
  92.         pos += bcount;
  93.         dpos += bcount;
  94.         dleft -= bcount;
  95.         if ( pos == rsize )    /* filled an entire row */
  96.            {
  97. #ifdef DEBUG
  98. if ( gs_debug['B'] )
  99.    {            int i, n = width * penum->spp;
  100.             dputs("[B]row:");
  101.             for ( i = 0; i < n; i++ )
  102.                 dprintf1(" %02x", penum->buffer[i]);
  103.             dputs("\n");
  104.    }
  105. #endif
  106.             if ( !penum->skewed )
  107.               { /* Precompute integer y and height, */
  108.                 /* and check for clipping. */
  109.                 fixed yc = penum->ycur, yn;
  110.                 fixed dyy = penum->fyy;
  111.                 fixed adjust = penum->adjust;
  112.                 if ( dyy > 0 )
  113.                   dyy += adjust << 1,
  114.                   yc -= adjust;
  115.                 else
  116.                   dyy = (adjust << 1) - dyy,
  117.                   yc -= dyy - adjust;
  118.                 if ( yc >= penum->clip_box.q.y ) goto mt;
  119.                 yn = yc + dyy;
  120.                 if ( yn <= penum->clip_box.p.y ) goto mt;
  121.                 penum->yci = fixed2int_var_rounded(yc);
  122.                 penum->hci =
  123.                   fixed2int_var_rounded(yn) - penum->yci;
  124.                 if ( penum->hci == 0 ) goto mt;
  125.               }
  126.             code = (*penum->render)(penum, penum->buffer, width * penum->spp, 1);
  127.             if ( code < 0 ) goto err;
  128. mt:            if ( ++(penum->y) == penum->height ) goto end;
  129.             pos = 0;
  130.             penum->xcur += penum->fyx;
  131.             penum->ycur += penum->fyy;
  132.            }
  133.        }
  134.     penum->byte_in_row = pos;
  135.     code = 0;
  136.     goto out;
  137. end:    /* End of data */
  138.     code = 1;
  139.     goto out;
  140. err:    /* Error or interrupt, restore original state. */
  141.     penum->plane_index = penum->spread - 1;
  142.     penum->xcur = xcur_save;
  143.     penum->ycur = ycur_save;
  144.     penum->y = y_save;
  145.     /* Note that caller must call gs_image_cleanup */
  146.     /* for both error and normal termination. */
  147. out:    if ( save_dev != 0 ) gx_set_device_only(pgs, save_dev);
  148.     return code;
  149. }
  150.  
  151. /* Clean up by releasing the buffers. */
  152. void
  153. gs_image_cleanup(register gs_image_enum *penum)
  154. {    if ( penum->buffer )
  155.     {    gs_free((char *)penum->buffer, 1, penum->buffer_size,
  156.             "image buffer");
  157.         penum->buffer = 0;
  158.     }
  159.     if ( penum->line )
  160.     {    gs_free((char *)penum->line, 1, penum->line_size,
  161.             "image line");
  162.         penum->line = 0;
  163.     }
  164. }
  165.  
  166. /* ------ Unpacking procedures ------ */
  167.  
  168. void
  169. image_unpack_1(const gs_image_enum *penum, const sample_map *pmap,
  170.   byte *bptr, register const byte *data, uint dsize, uint inpos)
  171. {    register ulong *bufp = (unsigned long *)bptr;
  172.     int left = dsize;
  173.     register const ulong *map = &pmap->table.lookup4x1to32[0];
  174.     register uint b;
  175.     if ( left & 1 )
  176.        {    b = data[0];
  177.         bufp[0] = map[b >> 4];
  178.         bufp[1] = map[b & 0xf];
  179.         data++, bufp += 2;
  180.        }
  181.     left >>= 1;
  182.     while ( left-- )
  183.        {    b = data[0];
  184.         bufp[0] = map[b >> 4];
  185.         bufp[1] = map[b & 0xf];
  186.         b = data[1];
  187.         bufp[2] = map[b >> 4];
  188.         bufp[3] = map[b & 0xf];
  189.         data += 2, bufp += 4;
  190.        }
  191. }
  192.  
  193. void
  194. image_unpack_2(const gs_image_enum *penum, const sample_map *pmap,
  195.   byte *bptr, register const byte *data, uint dsize, uint inpos)
  196. {    register ushort *bufp = (unsigned short *)bptr;
  197.     int left = dsize;
  198.     register const ushort *map = &pmap->table.lookup2x2to16[0];
  199.     while ( left-- )
  200.        {    register unsigned b = *data++;
  201.         *bufp++ = map[b >> 4];
  202.         *bufp++ = map[b & 0xf];
  203.        }
  204. }
  205.  
  206. void
  207. image_unpack_4(const gs_image_enum *penum, const sample_map *pmap,
  208.   register byte *bufp, register const byte *data, uint dsize, uint inpos)
  209. {    register int spread = penum->spread;
  210.     int left = dsize;
  211.     register const byte *map = &pmap->table.lookup8[0];
  212.     while ( left-- )
  213.        {    register unsigned b = *data++;
  214.         *bufp = map[b >> 4]; bufp += spread;
  215.         *bufp = map[b & 0xf]; bufp += spread;
  216.        }
  217. }
  218.  
  219. void
  220. image_unpack_8(const gs_image_enum *penum, const sample_map *ignore_pmap,
  221.   byte *bufp, const byte *data, uint dsize, uint inpos)
  222. {    if ( data != bufp ) memcpy(bufp, data, dsize);
  223. }
  224.  
  225. /* ------ Rendering procedures ------ */
  226.  
  227. /* Rendering procedure for ignoring an image.  We still need to iterate */
  228. /* over the samples, because the procedure might have side effects. */
  229. int
  230. image_render_skip(gs_image_enum *penum, byte *data, uint w, int h)
  231. {    return h;
  232. }
  233.  
  234. /* Rendering procedure for a monobit image with no */
  235. /* skew or rotation and pure colors. */
  236. int
  237. image_render_simple(gs_image_enum *penum, byte *buffer, uint w, int h)
  238. {    byte *line = penum->line;
  239.     uint line_size, line_width;
  240.     gx_device *dev = penum->pgs->device->info;
  241.     dev_proc_copy_mono((*copy_mono)) = dev->procs->copy_mono;
  242.     int ix = fixed2int_rounded(penum->xcur);
  243.     const int iy = penum->yci, ih = penum->hci;
  244.     gx_color_index
  245.         zero = penum->icolor0.color1,
  246.         one = penum->icolor1.color1;
  247.     int dy;
  248.  
  249.     if ( penum->map[0].table.lookup4x1to32[0] != 0 )
  250.         zero = penum->icolor1.color1,
  251.         one = penum->icolor0.color1;
  252.  
  253.     if ( line == 0 )
  254.     {    /* A direct BitBlt is possible. */
  255.         line = buffer;
  256.         line_size = (w + 7) >> 3;
  257.         line_width = w;
  258.     }
  259.     else
  260.     {    fixed xl = penum->xcur + fixed_half - int2fixed(ix);
  261.         const fixed dxx = penum->fxx;
  262.         const fixed dxx_4 = dxx << 2;
  263.         const fixed dxx_8 = dxx_4 << 1;
  264.         register const byte *psrc = buffer;
  265.         byte sbit = 0x80;
  266.         byte *endp = buffer + (w >> 3);
  267.         const byte endbit = 1 << (~w & 7);
  268.         byte data;
  269.  
  270.         line_size = penum->line_size;
  271.         line_width = penum->line_width;
  272.         if ( dxx < 0 )
  273.             ix -= line_width,
  274.             xl += int2fixed(line_width);
  275.  
  276.         /* Invert the bit following the last valid data bit. */
  277.         if ( endbit == 0x80 ) *endp = ~endp[-1] << 7;
  278.         else if ( *endp & (endbit << 1) ) *endp &= ~endbit;
  279.         else *endp |= endbit;
  280.         data = *psrc;
  281.  
  282.         memset(line, 0, line_size);
  283.         /*
  284.          * Loop invariants:
  285.          *    data = *psrc;
  286.          *    sbit = 1 << n, 0<=n<=7.
  287.          */
  288.         do
  289.         {    int x0, n, bit;
  290.             byte *bp;
  291.             static const byte lmasks[9] =
  292.              { 0xff, 0x7f, 0x3f, 0x1f, 0xf, 7, 3, 1, 0 };
  293.             static const byte rmasks[8] =
  294.              { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
  295.  
  296.             /* Scan a run of zeros. */
  297.             while ( ~data & sbit )
  298.             {    xl += dxx;
  299.                 sbit >>= 1;
  300.             }
  301.             if ( !sbit )
  302.             {    while ( (data = *++psrc) == 0 )
  303.                     xl += dxx_8;
  304.                 if ( data > 0xf )
  305.                     sbit = 0x80;
  306.                 else
  307.                     xl += dxx_4,
  308.                     sbit = 0x08;
  309.                 while ( ~data & sbit )
  310.                 {    xl += dxx;
  311.                     sbit >>= 1;
  312.                 }
  313.             }
  314.             if ( !(psrc < endp || sbit > endbit) )
  315.                 break;
  316.             x0 = fixed2int_var(xl);
  317.  
  318.             /* Scan a run of ones. */
  319.             while ( data & sbit )
  320.             {    xl += dxx;
  321.                 sbit >>= 1;
  322.             }
  323.             if ( !sbit )
  324.             {    while ( (data = *++psrc) == 0xff )
  325.                     xl += dxx_8;
  326.                 if ( data < 0xf0 )
  327.                     sbit = 0x80;
  328.                 else
  329.                     xl += dxx_4,
  330.                     sbit = 0x08;
  331.                 while ( data & sbit )
  332.                 {    xl += dxx;
  333.                     sbit >>= 1;
  334.                 }
  335.             }
  336.  
  337.             /* Fill the run in the scan line. */
  338.             n = fixed2int_var(xl) - x0;
  339.             if ( n < 0 ) x0 += n, n = -n;
  340.             bp = line + (x0 >> 3);
  341.             bit = x0 & 7;
  342.             if ( (n += bit) <= 8 )
  343.                 *bp |= lmasks[bit] - lmasks[n];
  344.             else
  345.             {    *bp++ |= lmasks[bit];
  346.                 if ( n > 64 )
  347.                 {    int nb = (n >> 3) - 1;
  348.                     memset(bp, 0xff, nb);
  349.                     bp += nb;
  350.                     n &= 7;
  351.                 }
  352.                 else
  353.                 {    n -= 8;
  354.                     while ( (n -= 8) >= 0 )
  355.                         *bp++ = 0xff;
  356.                 }
  357.                 *bp |= rmasks[n & 7];
  358.             }
  359.  
  360.         } while ( psrc < endp || sbit > endbit );
  361.     }
  362.  
  363.     /* Finally, transfer the scan line to the device. */
  364.     for ( dy = 0; dy < ih; dy++ )
  365.         (*copy_mono)(dev, line, 0, line_size, gx_no_bitmap_id,
  366.             ix, iy + dy, line_width, 1, zero, one);
  367.  
  368.     return_check_interrupt(1);
  369. }
  370.  
  371. /* Rendering procedure for the general case of displaying a */
  372. /* monochrome image, dealing with multiple bit-per-sample images, */
  373. /* general transformations, and arbitrary single-component */
  374. /* color spaces (DeviceGray, CIEBasedA, Separation, Indexed). */
  375. /* This procedure handles a single scan line. */
  376. int
  377. image_render_mono(gs_image_enum *penum, byte *buffer, uint w, int h)
  378. {    gs_state *pgs = penum->pgs;
  379.     const int masked = penum->masked;
  380.     const fixed dxx = penum->fxx;
  381.     fixed xt = penum->xcur;
  382.     gs_color_space *pcs = pgs->color_space;
  383.     cs_proc_remap_color((*remap_color)) = pcs->type->remap_color;
  384.     gs_client_color cc;
  385.     cmap_proc_gray((*map_gray)) = pgs->cmap_procs->map_gray;
  386.     gx_device_color *pdevc = pgs->dev_color;
  387.     /* Make sure the cache setup matches the graphics state. */
  388.     /* Also determine whether all tiles fit in the cache. */
  389.     int tiles_fit = gx_check_tile_cache(pgs);
  390. #define image_set_gray(sample_value)\
  391.    { pdevc = &penum->dev_colors[sample_value];\
  392.      switch ( pdevc->halftone_level )\
  393.       { default:        /* halftone */\
  394.       if ( !tiles_fit ) gx_color_load(pdevc, pgs); break;\
  395.         case -1:        /* not computed yet */\
  396.       if ( penum->device_color )\
  397.         (*map_gray)(byte2frac(sample_value), pdevc, pgs);\
  398.       else\
  399.       { decode_sample(sample_value, cc, 0);\
  400.         (*remap_color)(&cc, pcs, pdevc, pgs);\
  401.       }\
  402.     case 0: ;        /* pure color */\
  403.       }\
  404.    }
  405.     fixed xl = xt;
  406.     register const byte *psrc = buffer;
  407.     byte *endp = buffer + w;
  408.     fixed xrun = xt;        /* x at start of run */
  409.     register byte run = *psrc;    /* run value */
  410.     int htrun =            /* halftone run value */
  411.       (masked ? 255 : -2);
  412.  
  413.     *endp = ~endp[-1];    /* force end of run */
  414.     if ( penum->slow_loop )
  415.       { /* Skewed, or imagemask with a halftone. */
  416.         const fixed
  417.           dxy = penum->fxy, dyx = penum->fyx,
  418.           dyy = penum->fyy;
  419.         fixed ytf = penum->ycur;
  420.         fixed yrun = ytf;
  421.         int code;
  422.         for ( ; ; )
  423.           { if ( *psrc++ != run )
  424.           { /* Fill the region between xrun and xl. */
  425.             if ( run != htrun )
  426.               { if ( run == 0 )
  427.               { if ( masked ) goto trans;
  428.               }
  429.             htrun = run;
  430.             image_set_gray(run);
  431.               }
  432.             code = gz_fill_pgram_fixed(xrun, yrun, xl - xrun,
  433.                            ytf - yrun, dyx, dyy,
  434.                            pdevc, pgs);
  435.             if ( code < 0 ) return code;
  436. trans:            if ( psrc > endp ) break;
  437.             yrun = ytf;
  438.             xrun = xl;
  439.             run = psrc[-1];
  440.           }
  441.         xl += dxx;
  442.         ytf += dxy;        /* harmless if no skew */
  443.           }
  444.       }
  445.     else            /* fast loop */
  446.       { /* No skew, and not imagemask with a halftone. */
  447.         const fixed adjust = penum->adjust;
  448.         fixed xa = (dxx >= 0 ? adjust : -adjust);
  449.         const int yt = penum->yci, iht = penum->hci;
  450.         gx_device *dev = pgs->device->info;
  451.         dev_proc_fill_rectangle((*fill_proc)) = dev->procs->fill_rectangle;
  452.         dev_proc_tile_rectangle((*tile_proc)) = dev->procs->tile_rectangle;
  453.         dev_proc_copy_mono((*copy_mono_proc)) = dev->procs->copy_mono;
  454.         dev_proc_copy_color((*copy_color_proc)) = dev->procs->copy_color;
  455.         /* If each pixel is likely to fit in a single halftone tile, */
  456.         /* determine that now (tile_offset = offset of row within tile). */
  457.         int tile_offset =
  458.           gx_check_tile_size(pgs,
  459.                  fixed2int_rounded(any_abs(dxx) + (xa << 1)),
  460.                  yt, iht);
  461.         /* Fold the adjustment into xrun and xl, */
  462.         /* including the +0.5 for rounding. */
  463.         xrun = xrun - xa + fixed_half;
  464.         xl = xl + xa + fixed_half;
  465.         xa <<= 1;
  466.         for ( ; ; )
  467.           { /* Skip large constant regions quickly, */
  468.             /* but don't slow down transitions too much. */
  469.             while ( psrc[0] == run )
  470.         { if ( psrc[1] == run )
  471.           { if ( psrc[2] == run )
  472.             { if ( psrc[3] == run )
  473.               { psrc += 4, xl += dxx << 2;
  474.             continue;
  475.               }
  476.               else
  477.                 psrc += 3, xl += (dxx << 1) + dxx;
  478.             }
  479.             else
  480.               psrc += 2, xl += dxx << 1;
  481.           }
  482.           else
  483.             psrc++, xl += dxx;
  484.           break;
  485.         }
  486.         psrc++;
  487.           { /* Fill the region between xrun and xl. */
  488.             int xi = fixed2int_var(xrun);
  489.             int wi = fixed2int_var(xl) - xi;
  490.             int tsx, code;
  491.             gx_bitmap *tile;
  492.             if ( wi <= 0 )
  493.               { if ( wi == 0 ) goto mt;
  494.             xi += wi, wi = -wi;
  495.               }
  496.             switch ( run )
  497.               {
  498.               case 0:
  499.             if ( masked ) goto mt;
  500.             if ( !color_is_pure(&penum->icolor0) ) goto ht;
  501.             code = (*fill_proc)(dev, xi, yt, wi, iht, penum->icolor0.color1);
  502.             break;
  503.               case 255:        /* just for speed */
  504.             if ( !color_is_pure(&penum->icolor1) ) goto ht;
  505.             code = (*fill_proc)(dev, xi, yt, wi, iht, penum->icolor1.color1);
  506.             break;
  507.               default:
  508. ht:            /* Use halftone if needed */
  509.             if ( run != htrun )
  510.               { image_set_gray(run);
  511.                 htrun = run;
  512.               }
  513.             /* We open-code gz_fill_rectangle_open, */
  514.             /* because we've done some of the work for */
  515.             /* halftone tiles in advance. */
  516.             if ( color_is_pure(pdevc) )
  517.               { code = (*fill_proc)(dev, xi, yt, wi, iht, pdevc->color1);
  518.               }
  519.             else if ( tile_offset >= 0 &&
  520.                   (tile = pdevc->tile,
  521.                    (tsx = (xi + pgs->phase_mod.x) % tile->rep_width) + wi <= tile->size.x)
  522.                 )
  523.               { /* The pixel(s) fit(s) in a single tile. */
  524.                 byte *row = tile->data + tile_offset;
  525.                 code = (color_is_color_halftone(pdevc) ?
  526.                     (*copy_color_proc)
  527.                       (dev, row, tsx, tile->raster, gx_no_bitmap_id,
  528.                        xi, yt, wi, iht) :
  529.                     (*copy_mono_proc)
  530.                       (dev, row, tsx, tile->raster, gx_no_bitmap_id,
  531.                        xi, yt, wi, iht,
  532.                        pdevc->color1, pdevc->color2)
  533.                     );
  534.                 return_if_interrupt();
  535.               }
  536.             else
  537.               { code = (*tile_proc)(dev, pdevc->tile, xi, yt, wi, iht,
  538.                          pdevc->color1, pdevc->color2,
  539.                          pgs->phase_mod.x, pgs->phase_mod.y);
  540.               }
  541.               }
  542.             if ( code < 0 ) return code;
  543. mt:            if ( psrc > endp ) break;
  544.             xrun = xl - xa;    /* original xa << 1 */
  545.             run = psrc[-1];
  546.           }
  547.         xl += dxx;
  548.           }
  549.       }
  550.     return 1;
  551. }
  552.